home *** CD-ROM | disk | FTP | other *** search
/ Windows 95 API Bible / Windows 95 API Bible 3 Disc Set.iso / Win32 API Bible Book 2 of 3 / CHAPTER8 / RTFEDIT.C < prev    next >
C/C++ Source or Header  |  1996-03-06  |  38KB  |  1,244 lines

  1.  
  2. #include <windows.h>  
  3. #include <excpt.h>
  4. #include <richedit.h>
  5. #include <commctrl.h>
  6. #include "rtfedit.h"  
  7.  
  8.  
  9. #if defined (WIN32)
  10.     #define IS_WIN32 TRUE
  11. #else
  12.     #define IS_WIN32 FALSE
  13. #endif
  14.  
  15. #define IS_NT      IS_WIN32 && (BOOL)(GetVersion() < 0x80000000)
  16. #define IS_WIN32S  IS_WIN32 && (BOOL)(!(IS_NT) && (LOBYTE(LOWORD(GetVersion()))<4))
  17. #define IS_WIN95   (BOOL)(!(IS_NT) && !(IS_WIN32S)) && IS_WIN32
  18.  
  19. LPCTSTR lpszAppName = "MyApp";
  20. LPCTSTR lpszTitle   = "Rich-Text Editor"; 
  21.  
  22. HINSTANCE hInst;          // current instance
  23. HINSTANCE hRtfLib = NULL; // rich-text DLL instance
  24.  
  25. FINDREPLACE fr;
  26.  
  27. UINT nRTF;             // registered clipboard format for RTF
  28. HWND hMainWnd   = NULL; // Window handle for the application
  29. HWND hEdit      = NULL; // Window handle of rich-text edit control
  30. HWND hStatusWnd = NULL;
  31. HWND hDlgAbort  = NULL;
  32. HWND hFindWnd   = NULL;
  33. BOOL bAbort     = FALSE;
  34.  
  35. HANDLE ghDevMode  = NULL;
  36. HANDLE ghDevNames = NULL;
  37.  
  38. TCHAR szFindWhat[128];
  39.  
  40. #define MAXFILESIZE  0x000FFFFF
  41.  
  42. char szFileName[ MAX_PATH+1 ] = "\0";
  43.  
  44.  
  45. LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  46. {
  47. static RECT strect;
  48. static UINT nFindMsg = 0;
  49.  
  50.  
  51.    if ( uMsg == nFindMsg )
  52.    {
  53.       HandleFindMsg( (FINDREPLACE*)lParam );
  54.       return( 0 );
  55.    }
  56.  
  57.    switch( uMsg )
  58.    {
  59.       case WM_CREATE :
  60.               InitCommonControls();
  61.  
  62.               szFindWhat[0] = '\0';
  63.               nFindMsg = RegisterWindowMessage( "commdlg_FindReplace" );
  64.  
  65.               hRtfLib = LoadLibrary( "RICHED32.DLL" );
  66.               hEdit   = CreateWindowEx( WS_EX_CLIENTEDGE,
  67.                                         "RICHEDIT",
  68.                                         "",
  69.                                         WS_CHILD | WS_VISIBLE |
  70.                                         WS_BORDER | ES_MULTILINE |
  71.                                         WS_VSCROLL | WS_HSCROLL |
  72.                                         ES_AUTOVSCROLL | ES_NOHIDESEL,
  73.                                         0, 0,
  74.                                         0, 0,
  75.                                         hWnd,
  76.                                         (HMENU)1,
  77.                                         hInst,
  78.                                         NULL );
  79.  
  80.               hStatusWnd = CreateStatusWindow( 
  81.                                   WS_CHILD | WS_VISIBLE | 
  82.                                   CCS_BOTTOM | SBARS_SIZEGRIP, 
  83.                                   "", hWnd, 101 );
  84.  
  85.               // Register the RTF clipboard format.
  86.               //...................................
  87.               nRTF = RegisterClipboardFormat( CF_RTF );
  88.  
  89.               // Set the default Font.
  90.               //......................
  91.               if ( hEdit )
  92.               {
  93.                  CHARFORMAT cf;
  94.                  DWORD      dwEvent;
  95.  
  96.                  cf.cbSize = sizeof( CHARFORMAT );
  97.                  cf.dwMask = CFM_FACE | CFM_BOLD | CFM_UNDERLINE | 
  98.                              CFM_ITALIC | CFM_COLOR;
  99.                  cf.dwEffects = CFE_AUTOCOLOR;
  100.                  strcpy( cf.szFaceName, "Arial" );
  101.  
  102.                  SendMessage( hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
  103.                  SetFocus( hEdit );
  104.  
  105.                  // Set the event mask to return EN_SELCHANGE.
  106.                  //...........................................
  107.                  dwEvent = SendMessage( hEdit, EM_GETEVENTMASK, 0, 0 );
  108.                  dwEvent |= ENM_SELCHANGE;
  109.                  SendMessage( hEdit, EM_SETEVENTMASK, 0, dwEvent ); 
  110.  
  111.                  // Set the maximum number of characters.
  112.                  //......................................
  113.                  SendMessage( hEdit, EM_EXLIMITTEXT, 0, MAXFILESIZE );
  114.               }
  115.  
  116.               // Retrieve the status window size.
  117.               //.................................
  118.               if ( hStatusWnd )
  119.                  GetClientRect( hStatusWnd, &strect );
  120.  
  121.               break;
  122.  
  123.       case WM_SETFOCUS :
  124.               SetFocus( hEdit );
  125.               break;
  126.  
  127.       case WM_SIZE :
  128.               // Size the status window.
  129.               //........................
  130.               if ( hStatusWnd )
  131.               {
  132.                  int nParts[2];
  133.  
  134.                  MoveWindow( hStatusWnd, 0, HIWORD( lParam )-strect.bottom, 
  135.                              LOWORD( lParam ), HIWORD( lParam ), FALSE );
  136.  
  137.                  nParts[0] = LOWORD( lParam )-120;
  138.                  nParts[1] = -1;
  139.  
  140.                  SendMessage( hStatusWnd, SB_SETPARTS, 2, (LPARAM)nParts );
  141.               }
  142.  
  143.               // Size the edit window.
  144.               //......................
  145.               if ( hEdit )
  146.                  MoveWindow( hEdit,0,0, LOWORD(lParam), 
  147.                              HIWORD(lParam)-strect.bottom, TRUE );
  148.               break;
  149.  
  150.       case WM_INITMENUPOPUP :
  151.               switch( LOWORD( lParam ) )
  152.               {
  153.                 case 0 : HandleFileMenu( (HMENU)wParam ); break;
  154.                 case 1 : HandleEditMenu( (HMENU)wParam ); break;
  155.                 case 2 : HandleFormatMenu( (HMENU)wParam ); break;
  156.               }
  157.               break;
  158.  
  159.       case WM_NOTIFY :
  160.               switch( ((NMHDR*)lParam)->code )
  161.               {
  162.                  case EN_SELCHANGE :
  163.                       HandleSelChange( &((SELCHANGE*)lParam)->chrg );
  164.                       break;
  165.  
  166.                  case EN_SAVECLIPBOARD :
  167.                       if ( MessageBox( hWnd,
  168.                                        "Data is on the clipboard.\nDo you want to make it available?",
  169.                                        lpszTitle,
  170.                                        MB_YESNO | MB_ICONQUESTION ) == IDNO )
  171.                       {
  172.                          return( TRUE ); 
  173.                       } 
  174.                       break;
  175.                       
  176.                  case EN_STOPNOUNDO :
  177.                       if ( MessageBox( hWnd,
  178.                                        "This operation is too big to be undone.\n" \
  179.                                        "Do you want to continue without undo?",
  180.                                        lpszTitle,
  181.                                        MB_YESNO | MB_ICONQUESTION ) == IDNO )
  182.                       {
  183.                          return( TRUE );
  184.                       }                                      
  185.                       break;
  186.               }
  187.               break;
  188.  
  189.       case WM_COMMAND :
  190.               switch( LOWORD( wParam ) )
  191.               {
  192.                  // File menu items.
  193.                  //.................
  194.                  case IDM_NEW   : 
  195.                         SendMessage( hEdit, WM_SETTEXT, 0, 0 ); 
  196.                         SendMessage( hEdit, EM_SETMODIFY, 0, 0 );
  197.                         break;
  198.  
  199.                  case IDM_OPEN  : Open(); break;
  200.                  case IDM_SAVE  : Save(); break;
  201.                  case IDM_SAVEAS: SaveAs(); break; 
  202.                  case IDM_PRINT : Print(); break;
  203.                  case IDM_EXIT  : DestroyWindow( hWnd ); break;
  204.  
  205.                  // Edit menu items.
  206.                  //.................
  207.                  case IDM_UNDO  : SendMessage( hEdit, WM_UNDO, 0, 0 ); break;
  208.                  case IDM_CUT   : SendMessage( hEdit, WM_CUT, 0, 0 ); break;
  209.                  case IDM_COPY  : SendMessage( hEdit, WM_COPY, 0, 0 ); break;
  210.                  case IDM_PASTE : PasteClipboard(); break;
  211.                  case IDM_DELETE: SendMessage( hEdit, WM_CLEAR, 0, 0 ); break;
  212.                  case IDM_SELECTALL : 
  213.                         {
  214.                            CHARRANGE cr;
  215.  
  216.                            cr.cpMin = 0;
  217.                            cr.cpMax = -1;
  218.                            SendMessage( hEdit, EM_EXSETSEL, 0, (LPARAM)&cr );
  219.                         }
  220.                         break;
  221.  
  222.                  case IDM_FIND :
  223.                         if ( !hFindWnd )
  224.                         {
  225.                            fr.lStructSize   = sizeof( FINDREPLACE );
  226.                            fr.hwndOwner     = hWnd;
  227.                            fr.lpstrFindWhat = szFindWhat;
  228.                            fr.Flags         = FR_NOUPDOWN;
  229.                            fr.wFindWhatLen  = sizeof( szFindWhat );
  230.  
  231.                            hFindWnd = FindText( &fr );
  232.  
  233.                            CommDlgExtendedError();
  234.                         }
  235.                         else
  236.                            SetFocus( hFindWnd );
  237.                         break;
  238.  
  239.                  case IDM_NEXTWORD :
  240.                         {
  241.                            CHARRANGE cr;
  242.                            
  243.                            SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&cr ); 
  244.  
  245.                            // Retrieve the position of the next word.
  246.                            //........................................
  247.                            cr.cpMin = SendMessage( hEdit, EM_FINDWORDBREAK,
  248.                                                    WB_RIGHT, cr.cpMax );
  249.  
  250.                            cr.cpMax = SendMessage( hEdit, EM_FINDWORDBREAK,
  251.                                                    WB_RIGHTBREAK, cr.cpMin );
  252.  
  253.                            SendMessage( hEdit, EM_EXSETSEL, 0, (LPARAM)&cr );
  254.                         }
  255.                         break;
  256.  
  257.                  // Format menu items.
  258.                  //...................
  259.                  case IDM_BOLD :
  260.                  case IDM_ITALIC :
  261.                  case IDM_UNDERLINE : 
  262.                         ChangeCharFormat( LOWORD( wParam ) );
  263.                         break;
  264.  
  265.                  case IDM_ALIGNLEFT :
  266.                  case IDM_ALIGNCENTER :
  267.                  case IDM_ALIGNRIGHT :
  268.                         ChangeAlignment( LOWORD( wParam ) );
  269.                         break;
  270.  
  271.                  case IDM_FONT :
  272.                         ChangeFont();
  273.                         break;
  274.                  
  275.                  // Help menu items.
  276.                  //.................
  277.                  case IDM_ABOUT :
  278.                         DialogBox( hInst, "AboutBox", hWnd, (DLGPROC)About );
  279.                         break;
  280.               }
  281.               break;
  282.       
  283.       case WM_DESTROY :
  284.               if ( ghDevMode ) GlobalFree( ghDevMode );
  285.               if ( ghDevNames ) GlobalFree( ghDevNames );
  286.  
  287.               // Delete the edit window so the EN_SAVECLIPBOARD
  288.               // notification can be processed before it is too late.
  289.               //.....................................................
  290.               DestroyWindow( hEdit );
  291.  
  292.               PostQuitMessage( 0 );
  293.               break;
  294.                                                                                     
  295.       default :
  296.             return( DefWindowProc( hWnd, uMsg, wParam, lParam ) );
  297.    }
  298.  
  299.    return( 0L );
  300. }
  301.  
  302. //***********************************************************
  303. //***********************************************************
  304. // Notification Handlers.
  305. //.......................
  306.  
  307. VOID HandleFindMsg( FINDREPLACE* pFR )
  308. {
  309.    if ( pFR->Flags & FR_FINDNEXT )
  310.    {
  311.       FINDTEXTEX ft;
  312.       LONG       lPos;
  313.       UINT       uFlags = pFR->Flags;
  314.  
  315.       // Retrieve current position.
  316.       //...........................
  317.       SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&ft.chrg ); 
  318.  
  319.       // Increment the position by 1 to skip where we are.
  320.       //..................................................
  321.       ft.chrg.cpMin++;
  322.  
  323.       // Search to the end of the text.
  324.       //...............................
  325.       ft.chrg.cpMax = -1;
  326.  
  327.       ft.lpstrText  = pFR->lpstrFindWhat;
  328.  
  329.       lPos = SendMessage( hEdit, EM_FINDTEXTEX, uFlags, (LPARAM)&ft );
  330.  
  331.       if ( lPos > -1 )
  332.          SendMessage( hEdit, EM_EXSETSEL, 0, (LPARAM)&ft.chrgText );
  333.       else
  334.          MessageBox( hMainWnd, "Text not found.", "Find", MB_OK | MB_ICONINFORMATION );
  335.    }
  336.  
  337.    // The user closed the Find dialog.
  338.    //.................................   
  339.    if ( pFR->Flags & FR_DIALOGTERM )
  340.       hFindWnd = NULL;
  341. }
  342.  
  343.  
  344. VOID HandleSelChange( CHARRANGE* cr )
  345. {
  346.    static char szTmp[32];
  347.    int nLineMin, nLineMax;
  348.  
  349.    // Retrieve the line number of the positions.
  350.    //...........................................
  351.    nLineMin = SendMessage( hEdit, EM_LINEFROMCHAR, 
  352.                            cr->cpMin, 0 );
  353.    nLineMax = SendMessage( hEdit, EM_LINEFROMCHAR, 
  354.                            cr->cpMax, 0 );
  355.  
  356.    // Display the line pos.
  357.    //......................
  358.    if ( cr->cpMin != cr->cpMax )
  359.    {
  360.       if ( nLineMin != nLineMax )
  361.          wsprintf( szTmp, "Ln %d:%d, Pos %d:%d", 
  362.                    nLineMin+1, nLineMax+1,
  363.                    cr->cpMin+1, 
  364.                    cr->cpMax+1 );
  365.       else
  366.          wsprintf( szTmp, "Ln %d, Pos %d:%d", 
  367.                    nLineMin+1, cr->cpMin+1, 
  368.                    cr->cpMax+1 );
  369.    }
  370.    else
  371.       wsprintf( szTmp, "Ln %d, Pos %d", 
  372.                 nLineMin+1, cr->cpMin+1 );
  373.  
  374.    SendMessage( hStatusWnd, SB_SETTEXT, 1, (LPARAM)szTmp );
  375. }
  376.  
  377. //***********************************************************
  378. //***********************************************************
  379. // Menu item Initialize Functions.
  380. //................................
  381.  
  382. VOID HandleFileMenu( HMENU hMenu )
  383. {
  384.    // Set the save menu item.
  385.    //........................
  386.    EnableMenuItem( hMenu, IDM_SAVE, MF_BYCOMMAND | 
  387.                    SendMessage( hEdit, EM_GETMODIFY, 0, 0 ) ?
  388.                    MF_ENABLED : MF_GRAYED );
  389. }
  390.  
  391. VOID HandleEditMenu( HMENU hMenu )
  392. {
  393.    CHARRANGE cr;
  394.    UINT      uEnable;
  395.  
  396.    // Set the Paste menu item.
  397.    //.........................
  398.    if ( OpenClipboard( hMainWnd ) )
  399.    {
  400.       // Check to see if one of these formats is available.
  401.       //...................................................
  402.       if ( IsClipboardFormatAvailable( CF_TEXT ) ||
  403.            IsClipboardFormatAvailable( nRTF ) )
  404.          EnableMenuItem( hMenu, IDM_PASTE, MF_BYCOMMAND | MF_ENABLED );
  405.       else
  406.          EnableMenuItem( hMenu, IDM_PASTE, MF_BYCOMMAND | MF_GRAYED );
  407.  
  408.       CloseClipboard();
  409.    }
  410.  
  411.    // Set the Cut/Copy/Delete menu items.
  412.    //.............................
  413.    SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&cr );
  414.    uEnable = cr.cpMin != cr.cpMax ? MF_ENABLED : MF_GRAYED;
  415.  
  416.    EnableMenuItem( hMenu, IDM_CUT, MF_BYCOMMAND | uEnable );
  417.    EnableMenuItem( hMenu, IDM_COPY, MF_BYCOMMAND | uEnable );
  418.    EnableMenuItem( hMenu, IDM_DELETE, MF_BYCOMMAND | uEnable );
  419.  
  420.    // Set the Select All menu item.
  421.    //..............................
  422.    if ( SendMessage( hEdit, WM_GETTEXTLENGTH, 0, 0 ) )
  423.       EnableMenuItem( hMenu, IDM_SELECTALL, MF_BYCOMMAND | MF_ENABLED );
  424.    else
  425.       EnableMenuItem( hMenu, IDM_SELECTALL, MF_BYCOMMAND | MF_GRAYED );
  426. }
  427.  
  428.  
  429. VOID HandleFormatMenu( HMENU hMenu )
  430. {
  431.    CHARFORMAT cf;
  432.    PARAFORMAT pf;
  433.  
  434.    cf.cbSize = sizeof( CHARFORMAT );
  435.    SendMessage( hEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf );
  436.  
  437.    // Set the Bold/Italic/Underline menu items
  438.    //.........................................
  439.    if ( cf.dwMask & CFM_BOLD )
  440.       CheckMenuItem( hMenu, IDM_BOLD, MF_BYCOMMAND | 
  441.                       (cf.dwEffects & CFE_BOLD) ? 
  442.                      MF_CHECKED : MF_UNCHECKED );
  443.  
  444.    if ( cf.dwMask & CFM_ITALIC )
  445.       CheckMenuItem( hMenu, IDM_ITALIC, MF_BYCOMMAND |
  446.                       (cf.dwEffects & CFE_ITALIC) ?
  447.                      MF_CHECKED : MF_UNCHECKED );
  448.  
  449.    if ( cf.dwMask & CFM_UNDERLINE )
  450.       CheckMenuItem( hMenu, IDM_UNDERLINE, MF_BYCOMMAND |
  451.                       (cf.dwEffects & CFE_UNDERLINE) ?
  452.                      MF_CHECKED : MF_UNCHECKED );
  453.  
  454.    pf.cbSize = sizeof( PARAFORMAT );
  455.    SendMessage( hEdit, EM_GETPARAFORMAT, TRUE, (LPARAM)&pf );
  456.  
  457.    if ( pf.dwMask & PFM_ALIGNMENT )
  458.       CheckMenuRadioItem( hMenu, IDM_ALIGNLEFT, IDM_ALIGNRIGHT, 
  459.                     pf.wAlignment == PFA_LEFT ? IDM_ALIGNLEFT :
  460.                     pf.wAlignment == PFA_CENTER ? IDM_ALIGNCENTER :
  461.                     IDM_ALIGNRIGHT,  MF_BYCOMMAND );
  462. }
  463.  
  464. //***********************************************************
  465. //***********************************************************
  466. // Menu item handler Functions.
  467. //.............................
  468.  
  469.  
  470. DWORD CALLBACK ReadProc( DWORD dwCookie, LPBYTE pbBuff, 
  471.                          LONG cb, LONG* pcb )
  472. {
  473.    // Read the data from the file.
  474.    //.............................
  475.    ReadFile( (HANDLE)dwCookie,
  476.              pbBuff, cb,
  477.              pcb,
  478.              NULL );
  479.  
  480.    return( FALSE );
  481. }
  482.  
  483.  
  484. DWORD CALLBACK SaveProc( DWORD dwCookie, LPBYTE pbBuff, 
  485.                          LONG cb, LONG* pcb )
  486. {
  487.    // Write the data to the file.
  488.    //............................
  489.    if ( WriteFile( (HANDLE)dwCookie,
  490.                    pbBuff, cb,
  491.                    pcb,
  492.                    NULL ) )
  493.    {
  494.       return( TRUE );
  495.    }
  496.  
  497.    return( FALSE );
  498. }
  499.  
  500.  
  501. VOID Open()
  502. {
  503.    OPENFILENAME ofn;
  504.  
  505.    memset( &ofn, 0, sizeof( OPENFILENAME ) );
  506.  
  507.    // Fill OPENFILENAME structure.
  508.    //.............................
  509.    ofn.lStructSize = sizeof( OPENFILENAME );
  510.    ofn.hwndOwner   = hMainWnd;
  511.    ofn.lpstrFilter = "Rich-Text File (*.RTF)\0*.RTF\0\0";
  512.    ofn.lpstrFile   = szFileName;
  513.    ofn.nMaxFile    = MAX_PATH;
  514.    ofn.Flags       = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  515.    ofn.lpstrDefExt = "RTF";
  516.  
  517.    // Get a filename and save the file.
  518.    //..................................
  519.    if ( GetOpenFileName( &ofn ) )
  520.    {
  521.       EDITSTREAM es;
  522.       HANDLE     hFile;
  523.  
  524.       // Open the file.
  525.       //...............
  526.       hFile = CreateFile( szFileName, GENERIC_READ, 0, NULL, 
  527.                           OPEN_EXISTING, 
  528.                           FILE_ATTRIBUTE_NORMAL,
  529.                           NULL );      
  530.  
  531.       if ( hFile )
  532.       {
  533.          // Fill the EDITSTREAM structure.
  534.          //...............................
  535.          es.dwCookie = (DWORD)hFile;
  536.          es.dwError  = 0;
  537.          es.pfnCallback = ReadProc;
  538.  
  539.          // Read the data from the file.
  540.          //.............................
  541.          SendMessage( hEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es );
  542.  
  543.          // Clear the modify flag.
  544.          //.......................
  545.          SendMessage( hEdit, EM_SETMODIFY, 0, 0 );
  546.       }
  547.  
  548.       CloseHandle( hFile );
  549.    }
  550. }
  551.  
  552.  
  553. VOID Save()
  554. {
  555.    // If there is no filename,
  556.    // go to save as.
  557.    //.........................
  558.    if ( !szFileName[0] )
  559.       SaveAs();
  560.    else
  561.    {
  562.       EDITSTREAM es;
  563.       HANDLE     hFile;
  564.  
  565.       // Create a new file, always.
  566.       //...........................
  567.       hFile = CreateFile( szFileName, GENERIC_WRITE, 0, NULL, 
  568.                           CREATE_ALWAYS, 
  569.                           FILE_ATTRIBUTE_NORMAL |
  570.                           FILE_FLAG_WRITE_THROUGH,
  571.                           NULL );      
  572.  
  573.       // Fill the EDITSTREAM structure.
  574.       //...............................
  575.       es.dwCookie = (DWORD)hFile;
  576.       es.dwError  = 0;
  577.       es.pfnCallback = SaveProc;
  578.  
  579.       // Save the data to the file.
  580.       //...........................
  581.       SendMessage( hEdit, EM_STREAMOUT, SF_RTF, (LPARAM)&es );
  582.  
  583.       // Clear the modify flag.
  584.       //.......................
  585.       SendMessage( hEdit, EM_SETMODIFY, 0, 0 );
  586.  
  587.       CloseHandle( hFile );
  588.    }
  589. }
  590.  
  591.  
  592. VOID SaveAs()
  593. {
  594.    OPENFILENAME ofn;
  595.  
  596.    memset( &ofn, 0, sizeof( OPENFILENAME ) );
  597.  
  598.    // Fill OPENFILENAME structure.
  599.    //.............................
  600.    ofn.lStructSize = sizeof( OPENFILENAME );
  601.    ofn.hwndOwner   = hMainWnd;
  602.    ofn.lpstrFilter = "Rich-Text File (*.RTF)\0*.RTF\0\0";
  603.    ofn.lpstrFile   = szFileName;
  604.    ofn.nMaxFile    = MAX_PATH;
  605.    ofn.Flags       = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  606.    ofn.lpstrDefExt = "RTF";
  607.  
  608.    // Get a filename and save the file.
  609.    //..................................
  610.    if ( GetSaveFileName( &ofn ) )
  611.       Save();
  612. }
  613.  
  614.  
  615. VOID Print()
  616. {
  617.    PRINTDLG pd;
  618.  
  619.    // Default settings, these can change 
  620.    // once the user has gone through the print process.
  621.    //..................................................
  622.    static DWORD Flags     = PD_ALLPAGES | PD_SHOWHELP | PD_RETURNDC;
  623.    static WORD  nFromPage = 0xFFFF;
  624.    static WORD  nToPage   = 0xFFFF;
  625.    static WORD  nCopies   = 1;
  626.  
  627.    memset( &pd, 0, sizeof( PRINTDLG ) );
  628.  
  629.    pd.lStructSize = sizeof(pd);
  630.    pd.hwndOwner   = hMainWnd;
  631.    pd.hDevMode    = ghDevMode;
  632.    pd.hDevNames   = ghDevNames;
  633.    pd.Flags       = Flags;
  634.    pd.nFromPage   = nFromPage;
  635.    pd.nToPage     = nToPage;
  636.    pd.nMinPage    = 0;
  637.    pd.nMaxPage    = 0xFFFF;
  638.    pd.nCopies     = nCopies;
  639.  
  640.    if ( PrintDlg(&pd) )
  641.    {
  642.       // Actually Print the document.
  643.       //.............................
  644.       PrintDocument( &pd );
  645.  
  646.       // Save the settings as the defaults.
  647.       //...................................
  648.       ghDevMode  = pd.hDevMode;
  649.       ghDevNames = pd.hDevNames;
  650.       Flags      = pd.Flags;
  651.       nFromPage  = pd.nFromPage;
  652.       nToPage    = pd.nToPage;
  653.       nCopies    = pd.nCopies;
  654.    }
  655. }
  656.  
  657.  
  658. VOID PasteClipboard()
  659. {
  660.    if ( OpenClipboard( hMainWnd ) )
  661.    {
  662.       // Check if the clipboard format is RTF.
  663.       //......................................
  664.       BOOL bRTF = IsClipboardFormatAvailable( nRTF );
  665.  
  666.       CloseClipboard();
  667.  
  668.       // Paste the clipboard contents into the 
  669.       // rich-text edit control. 
  670.       // The RTF format is preferred.
  671.       //......................................
  672.       SendMessage( hEdit, EM_PASTESPECIAL, 
  673.                           bRTF ? nRTF : CF_TEXT, 0 );
  674.    }
  675.    SetFocus( hEdit );
  676. }
  677.  
  678.  
  679. VOID ChangeCharFormat( UINT uCmd )
  680. {
  681.    CHARFORMAT cf;
  682.  
  683.    // Retrieve the current setting.
  684.    //..............................
  685.    cf.cbSize = sizeof( CHARFORMAT );
  686.    SendMessage( hEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf );
  687.  
  688.    // Toggle the appropriate format.
  689.    //...............................
  690.    switch( uCmd )
  691.    {
  692.      case IDM_BOLD :
  693.             cf.dwMask = CFM_BOLD;
  694.             cf.dwEffects ^= CFE_BOLD;
  695.             break;       
  696.  
  697.      case IDM_ITALIC :
  698.             cf.dwMask = CFM_ITALIC;
  699.             cf.dwEffects ^= CFE_ITALIC;
  700.             break;       
  701.  
  702.      case IDM_UNDERLINE :
  703.             cf.dwMask = CFM_UNDERLINE;
  704.             cf.dwEffects ^= CFE_UNDERLINE;
  705.             break;       
  706.    }           
  707.  
  708.    // Make the change in the RTF edit control.
  709.    //.........................................
  710.    SendMessage( hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
  711.    SetFocus( hEdit );
  712. }
  713.  
  714.  
  715. VOID ChangeAlignment( UINT uCmd )
  716. {
  717.    PARAFORMAT pf;
  718.  
  719.    pf.cbSize = sizeof( PARAFORMAT );
  720.    pf.dwMask = PFM_ALIGNMENT;
  721.  
  722.    switch( uCmd )
  723.    {
  724.       case IDM_ALIGNLEFT   : pf.wAlignment = PFA_LEFT;   break;
  725.       case IDM_ALIGNCENTER : pf.wAlignment = PFA_CENTER; break;
  726.       case IDM_ALIGNRIGHT  : pf.wAlignment = PFA_RIGHT;  break;
  727.    }
  728.  
  729.    SendMessage( hEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf );
  730.    SetFocus( hEdit );
  731. }
  732.  
  733.  
  734. VOID ChangeFont()
  735. {
  736.    CHARFORMAT cf;
  737.    CHOOSEFONT chFont;
  738.    LOGFONT    lf;
  739.    HDC        hDC;
  740.  
  741.    // Retrieve the current font information.
  742.    //.......................................
  743.    cf.cbSize = sizeof( CHARFORMAT );
  744.    SendMessage( hEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf );
  745.  
  746.    memset( &chFont, 0, sizeof( CHOOSEFONT ) );
  747.    memset( &lf, 0, sizeof( LOGFONT ) );
  748.  
  749.    // Need a screen DC, use the parent's DC
  750.    hDC = GetDC( hMainWnd ); 
  751.  
  752.    // The RTF Edit control measures in twips, but LOGFONT measures
  753.    // in logical units (here, pixels) so we must convert.
  754.    //   1 point == 20 twips
  755.    //   1 inch  == 72 points
  756.    //     ==> 1 inch  == 1440 twips
  757.    //.............................................................
  758.    lf.lfHeight = MulDiv(cf.yHeight,
  759.                         GetDeviceCaps(hDC, LOGPIXELSY),
  760.                         -1440);
  761.  
  762.    ReleaseDC( hMainWnd, hDC );
  763.  
  764.    // Set up the rest of the logfont structure according to the 
  765.    // information retrieved from the EM_GETCHARFORMAT message.
  766.    //..........................................................
  767.    if ( cf.dwEffects & CFE_BOLD )
  768.       lf.lfWeight = FW_BOLD;
  769.    else
  770.       lf.lfWeight = FW_NORMAL;
  771.    lf.lfItalic = (BOOL)( cf.dwEffects & CFE_ITALIC );
  772.    lf.lfUnderline = (BOOL)( cf.dwEffects & CFE_UNDERLINE );
  773.    lf.lfCharSet = ANSI_CHARSET;
  774.    lf.lfQuality = DEFAULT_QUALITY;
  775.    lf.lfPitchAndFamily = cf.bPitchAndFamily;
  776.    strcpy( lf.lfFaceName, cf.szFaceName );
  777.  
  778.    // Set up the CHOOSEFONT structure.
  779.    //.................................
  780.    chFont.lStructSize = sizeof( CHOOSEFONT );
  781.    chFont.hwndOwner   = hMainWnd;
  782.    chFont.lpLogFont   = &lf;
  783.    chFont.hDC         = GetCurrentPrinterDC();
  784.    chFont.Flags       = CF_BOTH | CF_SCALABLEONLY | CF_WYSIWYG |
  785.                         CF_NOVECTORFONTS | CF_INITTOLOGFONTSTRUCT;
  786.  
  787.    if ( ChooseFont( &chFont ) )
  788.    {
  789.       // Set the flags for the values that we are setting. 
  790.       //..................................................
  791.       cf.dwMask = CFM_BOLD | CFM_FACE | CFM_ITALIC | 
  792.                   CFM_OFFSET | CFM_SIZE;
  793.  
  794.       // ChooseFont returns the new point size
  795.       // in tenths of a point so multiply by 2 to get 
  796.       // twips for the richedit control.
  797.       //.............................................
  798.       cf.yHeight = 2 * chFont.iPointSize;
  799.  
  800.       // Fill in the effects values.
  801.       //............................
  802.       cf.dwEffects = 0;
  803.       if ( lf.lfWeight >= FW_BOLD )
  804.          cf.dwEffects |= CFE_BOLD;
  805.       if ( lf.lfItalic )
  806.          cf.dwEffects |= CFE_ITALIC;
  807.  
  808.       cf.bPitchAndFamily = lf.lfPitchAndFamily;
  809.  
  810.       strcpy( cf.szFaceName, lf.lfFaceName );
  811.  
  812.       // Set the new formatting to the selected text.
  813.       //.............................................
  814.       SendMessage( hEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
  815.    }
  816.  
  817.    if ( chFont.hDC )
  818.       DeleteDC( chFont.hDC );
  819.  
  820.    SetFocus( hEdit );
  821. }
  822.  
  823.  
  824. //***********************************************************
  825. //***********************************************************
  826. // About Dialog Procedure.
  827. //........................
  828.  
  829. LRESULT CALLBACK About( HWND hDlg,           
  830.                         UINT message,        
  831.                         WPARAM wParam,       
  832.                         LPARAM lParam)
  833. {
  834.    switch (message) 
  835.    {
  836.        case WM_INITDIALOG: 
  837.                return (TRUE);
  838.  
  839.        case WM_COMMAND:                              
  840.                if (   LOWORD(wParam) == IDOK         
  841.                    || LOWORD(wParam) == IDCANCEL)    
  842.                {
  843.                        EndDialog(hDlg, TRUE);        
  844.                        return (TRUE);
  845.                }
  846.                break;
  847.    }
  848.  
  849.    return (FALSE); 
  850. }
  851.  
  852. //***********************************************************
  853. //***********************************************************
  854. // Application Initialization
  855. //...........................
  856.  
  857. BOOL RegisterWin95( CONST WNDCLASS* lpwc )
  858. {
  859.    WNDCLASSEX wcex;
  860.  
  861.    wcex.style         = lpwc->style;
  862.    wcex.lpfnWndProc   = lpwc->lpfnWndProc;
  863.    wcex.cbClsExtra    = lpwc->cbClsExtra;
  864.    wcex.cbWndExtra    = lpwc->cbWndExtra;
  865.    wcex.hInstance     = lpwc->hInstance;
  866.    wcex.hIcon         = lpwc->hIcon;
  867.    wcex.hCursor       = lpwc->hCursor;
  868.    wcex.hbrBackground = lpwc->hbrBackground;
  869.    wcex.lpszMenuName  = lpwc->lpszMenuName;
  870.    wcex.lpszClassName = lpwc->lpszClassName;
  871.  
  872.    // Added elements for Windows 95.
  873.    //...............................
  874.    wcex.cbSize = sizeof(WNDCLASSEX);
  875.    wcex.hIconSm = LoadImage(wcex.hInstance, lpwc->lpszClassName, 
  876.                             IMAGE_ICON, 16, 16,
  877.                             LR_DEFAULTCOLOR );
  878.             
  879.    return RegisterClassEx( &wcex );
  880. }
  881.  
  882.  
  883.  
  884. int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
  885.                       LPTSTR lpCmdLine, int nCmdShow)
  886. {
  887.    MSG      msg;
  888.    WNDCLASS wc;
  889.  
  890.    wc.style         = CS_HREDRAW | CS_VREDRAW;
  891.    wc.lpfnWndProc   = (WNDPROC)WndProc;       
  892.    wc.cbClsExtra    = 0;                      
  893.    wc.cbWndExtra    = 0;                      
  894.    wc.hInstance     = hInstance;              
  895.    wc.hIcon         = LoadIcon (hInstance, lpszAppName); 
  896.    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  897.    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  898.    wc.lpszMenuName  = lpszAppName;              
  899.    wc.lpszClassName = lpszAppName;              
  900.  
  901.    if ( IS_WIN95 )
  902.    {
  903.       if ( !RegisterWin95( &wc ) )
  904.          return( FALSE );
  905.    }
  906.    else if ( !RegisterClass( &wc ) )
  907.       return( FALSE );
  908.  
  909.    hInst = hInstance; 
  910.  
  911.    hMainWnd = CreateWindow( lpszAppName, 
  912.                         lpszTitle,    
  913.                         WS_OVERLAPPEDWINDOW, 
  914.                         CW_USEDEFAULT, 0, 
  915.                         CW_USEDEFAULT, 0,  
  916.                         NULL,              
  917.                         NULL,              
  918.                         hInstance,         
  919.                         NULL               
  920.                       );
  921.  
  922.    if ( !hMainWnd ) 
  923.       return( FALSE );
  924.  
  925.    ShowWindow( hMainWnd, nCmdShow ); 
  926.    UpdateWindow( hMainWnd );         
  927.  
  928.    while( GetMessage( &msg, NULL, 0, 0) )   
  929.    {
  930.       if ( hFindWnd && IsDialogMessage( hFindWnd, &msg ) )
  931.          continue;
  932.           
  933.       TranslateMessage( &msg ); 
  934.       DispatchMessage( &msg );  
  935.    }
  936.  
  937.    return( msg.wParam ); 
  938. }
  939.  
  940.  
  941. //***********************************************************
  942. //***********************************************************
  943. // Print Routines
  944. //...............
  945.  
  946. HDC GetCurrentPrinterDC()
  947. {
  948.     HDC hdc = NULL;
  949.  
  950.     // If we have already retrieved printer information,
  951.     // create the DC for that printer; otherwise, create
  952.     // the DC for the default system printer.
  953.     //..................................................
  954.     if ( ghDevNames )
  955.     {
  956.         LPDEVNAMES lpdn = (LPDEVNAMES)GlobalLock( ghDevNames );
  957.         LPDEVMODE lpdm = NULL;
  958.  
  959.         if ( ghDevMode )
  960.             lpdm = (LPDEVMODE)GlobalLock( ghDevMode );
  961.  
  962.         hdc = CreateDC((LPSTR)lpdn + lpdn->wDriverOffset,
  963.                        (LPSTR)lpdn + lpdn->wDeviceOffset,
  964.                        (LPSTR)lpdn + lpdn->wOutputOffset,
  965.                        lpdm);
  966.     }
  967.     else
  968.     {
  969.         PRINTDLG pd = {0};
  970.  
  971.         if ( ghDevMode )
  972.             GlobalFree( ghDevMode );
  973.  
  974.         pd.lStructSize = sizeof(pd);
  975.         pd.hwndOwner   = NULL;
  976.         pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
  977.  
  978.         if (PrintDlg(&pd))
  979.         {
  980.             ghDevMode = pd.hDevMode;
  981.             ghDevNames = pd.hDevNames;
  982.             hdc = pd.hDC;
  983.         }
  984.     }
  985.  
  986.     return hdc;
  987. }
  988.  
  989.  
  990. VOID PrintDocument( PRINTDLG* ppd )
  991. {
  992.    FORMATRANGE fr;
  993.    DOCINFO     di;
  994.    UINT        nPage, i, j, nCollateCopies;
  995.    LONG        lTextLength;
  996.    char        szTitle[MAX_PATH];
  997.    LPTSTR      szName;
  998.    RECT        rcTmp;
  999.  
  1000.    SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  1001.  
  1002.    // Clear the abort flag before setting 
  1003.    // abort proc or calling StartDoc.
  1004.    //....................................
  1005.    bAbort = FALSE;
  1006.  
  1007.    // Define the abort function.
  1008.    //...........................
  1009.    SetAbortProc( ppd->hDC, AbortProc );
  1010.  
  1011.    // Start the printing process.
  1012.    //............................
  1013.    memset( &di, 0, sizeof( DOCINFO ) );
  1014.  
  1015.    di.cbSize = sizeof(DOCINFO);
  1016.    szName = szFileName;
  1017.    if ( !GetFileTitle( szName, szTitle, sizeof(szTitle) ) )
  1018.      di.lpszDocName = szTitle;
  1019.    else
  1020.      di.lpszDocName = szName;
  1021.  
  1022.    di.lpszOutput = ( (ppd->Flags & PD_PRINTTOFILE) ? "FILE: " : NULL );
  1023.  
  1024.    try
  1025.    { 
  1026.       if ( StartDoc( ppd->hDC, &di ) < 0)
  1027.       {
  1028.          szName = "An error occured while trying to print.";
  1029.          RaiseException( 1, 0, 0, NULL );
  1030.       }
  1031.  
  1032.       // Create the modeless Abort dialog box.
  1033.       //......................................
  1034.       hDlgAbort = CreateDialog( hInst, "AbortDlg", 
  1035.                                 hMainWnd, AbortDlg );
  1036.  
  1037.       if ( !hDlgAbort )
  1038.       {
  1039.          szName = "The abort dialog count not be created.";
  1040.          RaiseException( 2, 0, 0, NULL );
  1041.       }
  1042.    }
  1043.    except ( EXCEPTION_EXECUTE_HANDLER )
  1044.    {
  1045.       SetCursor( LoadCursor( NULL, IDC_ARROW ) );
  1046.  
  1047.       MessageBox( hMainWnd, 
  1048.                   szName, 
  1049.                   lpszTitle, 
  1050.                   MB_OK | MB_ICONHAND );
  1051.  
  1052.       DeleteDC( ppd->hDC );
  1053.       return;
  1054.    }
  1055.  
  1056.    // Show Abort dialog.
  1057.    //...................
  1058.    ShowWindow( hDlgAbort, SW_NORMAL );
  1059.    UpdateWindow( hDlgAbort );
  1060.  
  1061.    // Disable the main window
  1062.    // to prevent the user from a 
  1063.    // menu option while printing.
  1064.    //............................
  1065.    EnableWindow( hMainWnd, FALSE );
  1066.    SetCursor( LoadCursor( NULL, IDC_ARROW ) );
  1067.  
  1068.    // Find out real size of document in characters.
  1069.    //..............................................
  1070.    lTextLength = SendMessage( hEdit, 
  1071.                               WM_GETTEXTLENGTH, 0, 0 );
  1072.  
  1073.    // Render to the same DC as the measure DC.
  1074.    //.........................................
  1075.    fr.hdc = ppd->hDC;
  1076.    fr.hdcTarget = ppd->hDC;
  1077.  
  1078.    // Set page rect to phys page size in twips
  1079.    //.........................................
  1080.    fr.rcPage.left   = 0;
  1081.    fr.rcPage.top    = 0;
  1082.    fr.rcPage.right  = MulDiv(
  1083.                         GetDeviceCaps( ppd->hDC, PHYSICALWIDTH ),
  1084.                         1440,
  1085.                         GetDeviceCaps( ppd->hDC, LOGPIXELSX ) );
  1086.  
  1087.    fr.rcPage.bottom = MulDiv(
  1088.                         GetDeviceCaps( ppd->hDC, PHYSICALHEIGHT ),
  1089.                         1440,
  1090.                         GetDeviceCaps( ppd->hDC, LOGPIXELSY ) );
  1091.  
  1092.    // Set up 3/4" horizontal and 1" vertical margins, 
  1093.    // with a minimum of 1" printable space in each direction.
  1094.    //........................................................
  1095.    fr.rc = fr.rcPage; // initially, the full page
  1096.  
  1097.    if ( fr.rcPage.right > (2*3*1440/4 + 1440) )
  1098.    {
  1099.       fr.rc.left = 3*1440/4;
  1100.       fr.rc.right -= 3*1440/4;
  1101.    }
  1102.    if ( fr.rcPage.bottom > 3*1440 )
  1103.    {
  1104.       fr.rc.top = 1440;
  1105.       fr.rc.bottom -= 1440;
  1106.    }
  1107.  
  1108.    // Keep a copy of the page size.
  1109.    //..............................
  1110.    rcTmp = fr.rc;  
  1111.  
  1112.    if ( ppd->Flags & PD_COLLATE )
  1113.    {
  1114.       nCollateCopies = ppd->nCopies;
  1115.       ppd->nCopies = 1;
  1116.    }
  1117.    else
  1118.       nCollateCopies = 1;
  1119.  
  1120.    for ( i=0; i < nCollateCopies && !bAbort; i++ )
  1121.    {
  1122.       nPage = 1;
  1123.  
  1124.       // Set range for the entire document (default)
  1125.       //............................................
  1126.       fr.chrg.cpMin = 0;
  1127.       fr.chrg.cpMax = lTextLength;
  1128.  
  1129.       // Are we only printing the current selection?
  1130.       //............................................
  1131.       if ( ppd->Flags & PD_SELECTION )
  1132.       {
  1133.          SendMessage( hEdit, EM_EXGETSEL, 0, (LPARAM)&fr.chrg );
  1134.          if ( fr.chrg.cpMax >= fr.chrg.cpMin )
  1135.             lTextLength = fr.chrg.cpMax;
  1136.       }
  1137.  
  1138.       // Perform the actual printing.
  1139.       //.............................
  1140.       do
  1141.       {
  1142.          // Format as much as will fit on a page. The return value
  1143.          // is the index of the first character on the next page.
  1144.          //.......................................................
  1145.          fr.chrg.cpMin = SendMessage( hEdit, 
  1146.                                       EM_FORMATRANGE, 
  1147.                                       FALSE,
  1148.                                       (LPARAM)&fr);
  1149.  
  1150.          // Print the page if supposed to.
  1151.          //...............................
  1152.          if ( !( (ppd->Flags & PD_PAGENUMS) && nPage < ppd->nFromPage ) )
  1153.          {
  1154.             for ( j=0; j < ppd->nCopies && !bAbort; j++ )
  1155.             {
  1156.                StartPage( ppd->hDC );
  1157.                SendMessage( hEdit, 
  1158.                             EM_DISPLAYBAND, 
  1159.                             0,
  1160.                             (LPARAM)&fr.rc);
  1161.                EndPage( ppd->hDC );
  1162.             }
  1163.          }
  1164.  
  1165.          // EM_FORMATRANGE modifies fr.rc.bottom, reset here.
  1166.          //..................................................
  1167.          fr.rc = rcTmp;  
  1168.  
  1169.          nPage++;       
  1170.  
  1171.          // Are we done?
  1172.          //.............
  1173.          if ( (ppd->Flags & PD_PAGENUMS) && nPage > ppd->nToPage )
  1174.             break;
  1175.       }
  1176.       while ( fr.chrg.cpMin < lTextLength && !bAbort );
  1177.    }  
  1178.  
  1179.    // Restore the RTF Edit controls position.
  1180.    //........................................
  1181.    SendMessage( hEdit, EM_FORMATRANGE, TRUE, (LPARAM)NULL );
  1182.  
  1183.    if ( !bAbort )
  1184.       EndDoc( ppd->hDC );
  1185.  
  1186.    // Clean up.
  1187.    //..........
  1188.    EnableWindow( hMainWnd, TRUE );
  1189.    DestroyWindow( hDlgAbort );
  1190.    DeleteDC( ppd->hDC );
  1191. }
  1192.  
  1193.  
  1194. BOOL CALLBACK AbortProc( HDC hdc, int Code )
  1195. {
  1196.    MSG msg;
  1197.  
  1198.    if ( !hDlgAbort )
  1199.       return( TRUE );
  1200.  
  1201.    // Message processing for the abort dialog box.
  1202.    //.............................................
  1203.    while ( !bAbort && PeekMessage( &msg, NULL, 0, 0, TRUE ) )
  1204.       if ( !IsDialogMessage( hDlgAbort, &msg ) )
  1205.       {
  1206.          TranslateMessage( &msg );
  1207.          DispatchMessage( &msg );
  1208.       }
  1209.  
  1210.    return( !bAbort );
  1211. }
  1212.  
  1213.  
  1214. LRESULT CALLBACK AbortDlg( HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam )
  1215. {
  1216.     switch( msg )
  1217.     {
  1218.         case WM_COMMAND:
  1219.             return( bAbort = TRUE );
  1220.  
  1221.         case WM_INITDIALOG:
  1222.             {
  1223.                char   szTitle[MAX_PATH];
  1224.                LPTSTR szName = szFileName;
  1225.  
  1226.                // Set the focus to the Cancel button.
  1227.                //....................................
  1228.                SetFocus( GetDlgItem( hdlg, IDCANCEL ) );
  1229.  
  1230.                // Retrieve the display name for the file
  1231.                // and set it in the abort dialog box.
  1232.                //.......................................
  1233.                if ( !GetFileTitle( szName, szTitle, sizeof(szTitle) ) )
  1234.                   szName = szTitle;
  1235.  
  1236.                SetDlgItemText( hdlg, IDC_FILENAME, (LPCTSTR)szName );
  1237.             }
  1238.             return( TRUE );
  1239.     }
  1240.  
  1241.     return( FALSE );
  1242. }
  1243.  
  1244.